package com.juyu.miliao.api.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.juyu.miliao.api.dao.mysql.MakeMoneyDao;
import com.juyu.miliao.api.dao.mysql.OpenApiStatusDao;
import com.juyu.miliao.api.dao.mysql.UserWalletDao;
import com.juyu.miliao.api.domain.*;
import com.juyu.miliao.api.rabbitMQ.PaySuccessRabbitMq;
import com.juyu.miliao.api.util.*;
import com.juyu.miliao.common.constant.EnumType;
import com.juyu.miliao.common.constant.SpendSystemMessage;
import com.juyu.miliao.common.constant.SpendSystemMessageType;
import com.juyu.miliao.common.domain.*;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.exception.IllegalParamException;
import com.juyu.miliao.common.util.CommonUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class PayService {
    private final Logger payNotifyLogger = LoggerFactory.getLogger("payNotify");
    @Resource
    UserWalletService userWalletService;
    @Resource
    OrderService orderService;

    @Resource
    UserVipService userVipService;
    @Resource
    private CoinPriceService coinPriceService;
    @Resource
    private VipService vipService;
    @Resource
    private PackageOnlineService packageOnlineService;
    @Resource
    private ConfigAppService configAppService;
    @Resource
    private VestRobotMessageService vestRobotMessageService;
    @Resource
    private PaySuccessRabbitMq paySuccessRabbitMq;
    @Resource
    private ConfigWxPayService configWxPayService;
    @Resource
    private AppKeyService appKeyService;
    @Resource
    private OpenApiStatusDao openApiStatusDao;
    @Resource
    private MakeMoneyDao makeMoneyDao;
    @Resource
    private UserWalletDao userWalletDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CoolSummerActivitiesService coolSummerActivitiesService;

    @Autowired
    private SystemMessageUtil systemMessageUtil;
    @Resource
    private BuyLimitService buyLimitService;
    @Resource
    private ObjectMapper objectMapper;

    @Transactional(rollbackFor = RuntimeException.class)
    public String zfbNotify(Map<String, String> params) throws Exception {
        // 校验成功后在response中返回success，校验失败返回failure
        if (params.get("app_id").equals(AlipayConfig.getAppId()) && params.get("trade_status").equals("TRADE_SUCCESS")) {
            // 根据自己的订单号查询数据并更新支付状态、保存支付宝订单号
            int temp = orderService.updateOrderById(params.get("out_trade_no"), params.get("trade_no"));
            if (temp == 1) {
                Order order = orderService.findOrderById(params.get("out_trade_no"));
                payNotifyLogger.info("支付宝更新订单成功---orderId={}", params.get("out_trade_no"));
                String passback = params.get("passback_params");
                passback = URLDecoder.decode(passback, "GBK");
                ObjectMapper mapper = new ObjectMapper();
                Map m = mapper.readValue(passback, Map.class);
                if (m.get("contentType").toString().equals("1")) {
                    userWalletService.changeUserWallet(Integer.parseInt(m.get("userId").toString()),
                            Integer.parseInt(m.get("contentId").toString()));
                    //用户支付成功维护user_wallet表recharge_amount 字段
                    userWalletService.changeRechargeAmount(Long.parseLong(m.get("userId").toString()),
                            Integer.parseInt(m.get("contentId").toString()), Integer.parseInt(m.get("contentType").toString()));
                } else if (m.get("contentType").toString().equals("2")
                        ||m.get("contentType").toString().equals("3")
                        ||m.get("contentType").toString().equals("4")) {
                    //2018-10-18 线下包需求
                    userVipService.changeUserVip(Integer.parseInt(m.get("userId").toString()),
                            Integer.parseInt(m.get("contentId").toString()),
                            Integer.parseInt(m.get("contentType").toString()),
                            order.getPayNum());
                    //用户支付成功维护user_wallet表recharge_amount 字段
                    userWalletService.changeRechargeAmount(Long.parseLong(m.get("userId").toString()),
                            Integer.parseInt(m.get("contentId").toString()), Integer.parseInt(m.get("contentType").toString()));
                } else if(m.get("contentType").toString().equals("5")) {
                    BuyLimit buyLimit = objectMapper.readValue(order.getExt(), BuyLimit.class);
                    buyLimitService.buy(Long.parseLong(m.get("userId").toString()), buyLimit);
                    userWalletService.changeRechargeAmount(Long.parseLong(m.get("userId").toString()), order.getFee());
                }
                //订单号放入rabbitmq中
                paySuccessRabbitMq.setPaySuccessInfo(params.get("out_trade_no"));
                paySuccessRabbitMq.setNewYearDayActivity(m.get("userId").toString(), Integer.parseInt(m.get("contentType").toString()));
                coolSummerActivitiesService.jackpot(order.getUserId(),order.getFee(),
                        order.getUpdateTime());
                //邀请赚钱 首冲用户判断逻辑
                makeMoneyRecharge(Long.parseLong(m.get("userId").toString()));
                spendBigCustomersMessage(order.getUserId(),order.getFee());
                return "success";
            } else {
                payNotifyLogger.info("支付宝更新订单失败---orderId={}", params.get("out_trade_no"));
            }
        } else {
            payNotifyLogger.info("支付宝回调支付失败---trade_status={}", params.get("trade_status").equals("TRADE_SUCCESS"));
        }
        return "failure";
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public String wxPayNotify(Map<String, String> notifyMap) throws Exception {
        Map<String, String> errorResult = new HashMap<String, String>(4);
        errorResult.put("return_code", "FAIL");
        errorResult.put("return_msg", "ERROR");
        String returnCode = notifyMap.get("return_code");
        payNotifyLogger.info("微信支付回调returnCode-" + returnCode);
        if ("SUCCESS".equals(returnCode.toUpperCase())) {
            String resultCode = notifyMap.get("result_code");
            String formSign = null;
            payNotifyLogger.info("微信支付回调resultCode-" + resultCode.toUpperCase());
            if ("SUCCESS".equals(resultCode.toUpperCase())) {
                formSign = notifyMap.get("sign");
                notifyMap.remove("sign");
                String attach = notifyMap.get("attach");
                //TODO
                payNotifyLogger.info("微信支付回调attach参数打印----attach{}", attach);
                if (attach == null || attach.isEmpty()) {
                    payNotifyLogger.info("微信支付回调attach为空");
                    return XmlUtil.returnInfoToXML(errorResult);
                }
                ObjectMapper mapper = new ObjectMapper();
                Map m = mapper.readValue(attach, Map.class);
                if (m == null) {
                    payNotifyLogger.info("微信支付回调attach map为空");
                    return XmlUtil.returnInfoToXML(errorResult);
                }
                String appPackageId = CommonUtil.null2String(m.get("appPackageId"));
                int phoneSystem = Integer.valueOf((String) m.get("phoneSystem"));
                int type = Integer.valueOf((String) m.get("wxPayType"));
                ConfigWxPay configWxPay = configWxPayService
                        .getConfigWxPayByAppPackageIdAndPhoneSystemAndType(appPackageId, Integer.valueOf(phoneSystem), type);
                String valiSign = Md5Util.signGFWXPayDataMD5(notifyMap, configWxPay.getKey());
                if (valiSign.equals(formSign)) {
                    String orderId = notifyMap.get("out_trade_no");
                    int temp = orderService.updateOrderById(orderId, notifyMap.get("transaction_id"));
                    if (temp == 1) {
                        Order order = orderService.findOrderById(orderId);
                        payNotifyLogger.info("微信更新订单成功---orderId={}", orderId);
                        if (m.get("contentType").toString().equals("1")) {
                            userWalletService.changeUserWallet(Integer.parseInt(m.get("userId").toString()),
                                    Integer.parseInt(m.get("contentId").toString()));
                        } else if (m.get("contentType").toString().equals("2")
                                    ||m.get("contentType").toString().equals("3")
                                    ||m.get("contentType").toString().equals("4")) {
                            //2018-10-18 线下包需求
                            userVipService.changeUserVip(Integer.parseInt(m.get("userId").toString()),
                                    Integer.parseInt(m.get("contentId").toString()),
                                    Integer.parseInt(m.get("contentType").toString()),
                                    order.getPayNum());
                        } else if(m.get("contentType").toString().equals("5")) {
                            BuyLimit buyLimit = objectMapper.readValue(order.getExt(), BuyLimit.class);
                            buyLimitService.buy(Long.parseLong(m.get("userId").toString()), buyLimit);
                        }
                        //用户支付成功维护user_wallet表recharge_amount 字段
                        userWalletService.changeRechargeAmount(Long.parseLong(m.get("userId").toString()),
                                Integer.parseInt(m.get("contentId").toString()), Integer.parseInt(m.get("contentType").toString()));
                        HashMap<String, String> returnMap = new HashMap<String, String>();
                        returnMap.put("return_code", "SUCCESS");
                        //订单支付成功,orderId 放 mq= queue.stat.order.message
                        paySuccessRabbitMq.setPaySuccessInfo(orderId);
                        paySuccessRabbitMq.setNewYearDayActivity(m.get("userId").toString(), Integer.parseInt(m.get("contentType").toString()));
                        coolSummerActivitiesService.jackpot(order.getUserId(),order.getFee(),
                                order.getUpdateTime());
                        //邀请赚钱 首冲用户判断逻辑
                        makeMoneyRecharge(Long.parseLong(m.get("userId").toString()));
                        spendBigCustomersMessage(order.getUserId(),order.getFee());
                        return XmlUtil.returnInfoToXML(returnMap);
                    }
                } else {
                    payNotifyLogger.info("微信支付回调签名未通过---valiSign.equals(formSign)={}", valiSign.equals(formSign));
                }
            }
        }
        return XmlUtil.returnInfoToXML(errorResult);
    }

    /**
     *
     * @param receipt
     * @param com
     * @param subject
     * @param contentType 1:金币，2：vip,3:svip,4:铂金VIP
     *                    (判断规则：1金币充值，2、3、4vip充值具体充值种类根据contentId查询VipClassification)
     * @param contentId
     * @param robotOrderType
     * @param h5OrderType
     * @param payNum 购买次数
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public void appleIapPay(String receipt, CommonHead com, Subject subject,
                            int contentType, int contentId,int robotOrderType,int h5OrderType,int payNum) throws IOException {
        JSONObject receiptJSON = JSONObject.parseObject(receipt);
        JSONArray in_appJSONArray = JSONObject.parseArray(receiptJSON.get("in_app").toString());
        if (in_appJSONArray.size() == 0) {
            payNotifyLogger.info("校验错误:in_appJSON为空,receipt-{}", receipt);
            throw new ConsumeRuntimeException("校验错误,in_appJSON为空");
        }
        String product_id = "";
        String out_trade_no = "";
        String receiptDate = receiptJSON.get("receipt_creation_date_ms").toString();
        for (int i = 0; i < in_appJSONArray.size(); i++) {
            String orPuDate = in_appJSONArray.getJSONObject(i).get("original_purchase_date_ms").toString();
            if (receiptDate.equals(orPuDate)) {
                product_id = in_appJSONArray.getJSONObject(i).get("product_id").toString();
                out_trade_no = in_appJSONArray.getJSONObject(i).get("transaction_id").toString();
            }
        }
        int OrderNum = orderService.findOrderByOutId(out_trade_no);
        if (OrderNum != 0) {
            payNotifyLogger.info("订单重复:outId-{},userId-{}", out_trade_no, subject.getId());
            throw new ConsumeRuntimeException("订单重复");
        }
        double fee = 0;
        if (contentType == 1) {
            CoinPrice coinPrice = coinPriceService.getCoinPriceById(contentId);
            if (coinPrice == null)
                throw new IllegalParamException("参数错误");
            String payKey = coinPrice.getCoinKey();
            if (!product_id.equals(payKey))
                throw new ConsumeRuntimeException("计费点error:product_id:" + product_id + ",payKey:" + payKey);
            fee = coinPrice.getPrice();
        }
        int vipClassification = 0;
        if (contentType == 2||contentType==3 || contentType == 4) {
            Vip vip = vipService.getVipById(contentId);
            if (vip == null)
                throw new IllegalParamException("参数错误");
            String payKey = vip.getVipKey();
            if (!product_id.equals(payKey))
                throw new ConsumeRuntimeException("计费点error:product_id:" + product_id + ",payKey:" + payKey);
            fee = vip.getPrice()*payNum;
            vipClassification = vip.getVipClassification()+1;
        }
        // 商户订单号，商户网站订单系统中唯一订单号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String order_id = ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date());
        Order order = new Order();
        order.setUserId(subject.getId());
        if(contentType==1){
            order.setContentType(contentType);
        }else{
            order.setContentType(vipClassification);
        }
        order.setFee(fee);
        order.setOrderId(order_id);
        order.setOutId(out_trade_no);
        order.setOrderStatus(1);
        order.setPayType(3);
        order.setContentId(contentId);
        order.setChannelId(subject.getChannel());
        order.setPhoneSystem(CommonUtil.null2Int(com.getPhoneSystem()));
        order.setVersionNum(com.getVersionNum());
        order.setAppPackageId(com.getAppPackageId());
        order.setGroupType(configAppService.getGroupType(com.getAppPackageId(), com.getPhoneSystem()));
        order.setOnline(packageOnlineService.getOnline(com));
        order.setConfigPayId("0");
        order.setRobotOrderType(robotOrderType);
        order.setH5OrderType(h5OrderType);
        order.setPayNum(payNum);
        orderService.insertOrder(order);
        if (contentType == 1) {
            userWalletService.changeUserWallet(subject.getId(), contentId);
        }
        if (contentType == 2||contentType==3||contentType == 4) {
            userVipService.changeUserVip(subject.getId(), contentId,contentType,payNum);
        }
        //订单支付成功,orderId 放 mq= queue.stat.order.message
        paySuccessRabbitMq.setPaySuccessInfo(order_id);
        paySuccessRabbitMq.setNewYearDayActivity(Long.toString(subject.getId()), contentType);
        //用户支付成功维护user_wallet表recharge_amount 字段
        userWalletService.changeRechargeAmount(subject.getId(), contentId, contentType);
        //邀请赚钱 首冲用户判断逻辑
        makeMoneyRecharge(subject.getId());
        spendBigCustomersMessage(order.getUserId(),order.getFee());
        try {
            payNotifyLogger.info("applePay发送H5校验信息com{},userId{}", com, subject.getId());
            ConfigApp configApp = configAppService.getConfigApp(com.getAppPackageId(), com.getPhoneSystem());
            if (configApp != null && com.getAppPackageId().equals(EnumType.PACKAGE_ID_XUNXUN_YONGHU.key)) {
                payNotifyLogger.info("applePay发送H5校验信息dto{},com{},userId{}",
                        configApp.toString(), com, subject.getId());
                sendPayInfoByIos(com.getChannel(), com.getVersionNum(), com.getAppPackageId(),
                        com.getPhoneSystem(), subject.getId());
            }
            coolSummerActivitiesService.jackpot(order.getUserId(),order.getFee(), LocalDateTime.now());
        } catch (UnsupportedEncodingException e) {
            payNotifyLogger.error("applePay发送H5消息异常", e);
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void appleIapPayNew(String receipt, CommonHead com, Subject subject,
                               int contentType, int contentId, String transactionId,
                               int robotOrderType,int h5OrderType,int payNum) throws IOException {
        JSONObject receiptJSON = JSONObject.parseObject(receipt);
        JSONArray in_appJSONArray = JSONObject.parseArray(receiptJSON.get("in_app").toString());
        if (in_appJSONArray.size() == 0) {
            payNotifyLogger.info("校验错误:in_appJSON为空,receipt-{}", receipt);
            throw new ConsumeRuntimeException("校验错误,in_appJSON为空");
        }
        String product_id = "";
        for (int i = 0; i < in_appJSONArray.size(); i++) {
            String transaction_id = in_appJSONArray.getJSONObject(i).get("transaction_id").toString();
            if (transactionId.equals(transaction_id)) {
                product_id = in_appJSONArray.getJSONObject(i).get("product_id").toString();
            }
        }
        int OrderNum = orderService.findOrderByOutId(transactionId);
        if (OrderNum != 0) {
            payNotifyLogger.info("订单重复:outId-{},userId-{}", transactionId, subject.getId());
            throw new ConsumeRuntimeException("订单重复");
        }
        double fee = 0;
        if (contentType == 1) {
            CoinPrice coinPrice = coinPriceService.getCoinPriceById(contentId);
            if (coinPrice == null)
                throw new IllegalParamException("参数错误");
            String payKey = coinPrice.getCoinKey();
            if (!product_id.equals(payKey))
                throw new ConsumeRuntimeException("计费点error:product_id:" + product_id + ",payKey:" + payKey);
            fee = coinPrice.getPrice();
        }
        if (contentType == 2||contentType==3 ||contentType==4) {
            Vip vip = vipService.getVipById(contentId);
            if (vip == null)
                throw new IllegalParamException("参数错误");
            String payKey = vip.getVipKey();
            if (!product_id.equals(payKey))
                throw new ConsumeRuntimeException("计费点error:product_id:" + product_id + ",payKey:" + payKey);
            fee = vip.getPrice()*payNum;
        }
        // 商户订单号，商户网站订单系统中唯一订单号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String order_id = ComputeRedPacketUtil.getRandom(100, 999) + sdf.format(new Date());
        Order order = new Order();
        order.setUserId(subject.getId());
        order.setContentType(contentType);
        order.setFee(fee);
        order.setOrderId(order_id);
        order.setOutId(transactionId);
        order.setOrderStatus(1);
        order.setPayType(3);
        order.setContentId(contentId);
        order.setChannelId(subject.getChannel());
        order.setPhoneSystem(CommonUtil.null2Int(com.getPhoneSystem()));
        order.setVersionNum(com.getVersionNum());
        order.setAppPackageId(com.getAppPackageId());
        order.setGroupType(configAppService.getGroupType(com.getAppPackageId(), com.getPhoneSystem()));
        order.setOnline(packageOnlineService.getOnline(com));
        order.setConfigPayId("0");
        order.setRobotOrderType(robotOrderType);
        order.setH5OrderType(h5OrderType);
        order.setPayNum(payNum);
        orderService.insertOrder(order);
        if (contentType == 1) {
            userWalletService.changeUserWallet(subject.getId(), contentId);
        }
        if (contentType == 2||contentType==3 ||contentType==4) {
            userVipService.changeUserVip(subject.getId(), contentId,contentType,payNum);
        }
        //同步到单机后台
//        try {
//            payNotifySGService.notifySG(order_id);
//        } catch (Exception e) {
//            payNotifyLogger.error("applePay发送同步消息异常", e);
//        }
        //订单支付成功,orderId 放 mq= queue.stat.order.message
        paySuccessRabbitMq.setPaySuccessInfo(order_id);
        paySuccessRabbitMq.setNewYearDayActivity(Long.toString(subject.getId()), contentType);
        //用户支付成功维护user_wallet表recharge_amount 字段
        userWalletService.changeRechargeAmount(subject.getId(), contentId, contentType);
        //邀请赚钱 首冲用户判断逻辑
        makeMoneyRecharge(subject.getId());
        spendBigCustomersMessage(order.getUserId(),order.getFee());
        try {
            payNotifyLogger.info("applePay发送H5校验信息com{},userId{}", com, subject.getId());
            ConfigApp configApp = configAppService.getConfigApp(com.getAppPackageId(), com.getPhoneSystem());
            if (configApp != null && com.getAppPackageId().equals(EnumType.PACKAGE_ID_XUNXUN_YONGHU.key)) {
                payNotifyLogger.info("applePay发送H5校验信息dto{},com{},userId{}",
                        configApp.toString(), com, subject.getId());
                sendPayInfoByIos(com.getChannel(), com.getVersionNum(), com.getAppPackageId(),
                        com.getPhoneSystem(), subject.getId());
            }
            coolSummerActivitiesService.jackpot(order.getUserId(),order.getFee(), LocalDateTime.now());
        } catch (UnsupportedEncodingException e) {
            payNotifyLogger.error("applePay发送H5消息异常", e);
        }
    }

    /**
     * ios用户支付成功，发送系统消息
     */
    private void sendPayInfoByIos(String channelId, String versionNum, String appPackageId,
                                  String phoneSystem, long userId) throws UnsupportedEncodingException {
        OpenApiStatus openApiStatus = openApiStatusDao.getOpenApiStatus(versionNum, Integer.parseInt(phoneSystem)
                , appPackageId, channelId);
        if(openApiStatus.getIsH5Buy()==1){
            String h5PayUrl = appKeyService.getAppKeyByKey("iosH5PayUrl").getValue();
            if (StringUtils.isEmpty(channelId)) {
                channelId = "default";
            }
            if (StringUtils.isEmpty(versionNum)) {
                versionNum = "default";
            }
            String parameter = "appPackageId=" + URLEncoder.encode(appPackageId, "UTF-8") +
                    "&channel=" + URLEncoder.encode(channelId, "UTF-8") + "&phoneSystem=" + phoneSystem +
                    "&versionNum=" + URLEncoder.encode(versionNum, "UTF-8") +
                    "&userId=" + userId;
            String url = h5PayUrl+"?" + parameter;

            Map<String,Object> ext = new HashMap<>(1);

            ext.put("redirectUrl",url);

            String template = SpendSystemMessage.IOS_PREFERENTIAL_RECHARGE.getMessage();
            ext.put("template",template);

            List<String> templateValueList = new ArrayList<>(1);
            templateValueList.add(url);

            ext.put("templateValue",templateValueList);

            String message = SpendSystemMessage.IOS_PREFERENTIAL_RECHARGE.getMessage(url);

            vestRobotMessageService.getSendMsg(userId,message,
                    SpendSystemMessageType.IOS_PREFERENTIAL_RECHARGE_TYPE.getCode(),ext);
        }
    }

    /**
     * 邀请赚钱 首冲用户判断逻辑
     */
    private void makeMoneyRecharge(long userId){
        //用户是否已存在首冲赠送记录
        MakeMoney rechargeMakeMoney = makeMoneyDao.getMakeMoneyByPassiveUserIdAndType(userId,2);
        if (rechargeMakeMoney != null){
            return;
        }
        //用户是否是被邀请用户
        MakeMoney logonMakeMoney = makeMoneyDao.getMakeMoneyByPassiveUserIdAndType(userId,1);
        if(logonMakeMoney == null){
            return;
        }
        int temp = makeMoneyDao.insertMakeMoney(logonMakeMoney.getActiveUserId(), userId ,2
                , EnumType.MAKE_MONEY_RECHARGE.state, logonMakeMoney.getVerifyOpenId()
                , logonMakeMoney.getVerifyDeviceNo());
        if(temp ==1){
            UserWallet userWallet = new UserWallet();
            userWallet.setUserId(logonMakeMoney.getActiveUserId());
            userWallet.setDeposit(EnumType.MAKE_MONEY_RECHARGE.state);
            userWalletDao.reviseDeposit(userWallet);
        }
    }

    public void spendBigCustomersMessage(long userId,double fee){
        if(fee >= 100){
            String key = RedisKeys.SPEND_BIG_CUSTOMERS_MESSAGE_NUM.getValue(userId+"");
            long num = stringRedisTemplate.opsForValue().increment(key,0);
            if(num<3){
                //发送消息
                String message = SpendSystemMessage.BIG_CUSTOMERS.getMessage();
                systemMessageUtil.spendBigCustomersMessage(userId,message);
                //更新发送次数
                stringRedisTemplate.opsForValue().increment(key,1);
            }

        }

    }
}
